package com.gs.zhss.eshop.common.util;

import java.util.HashMap;
import java.util.Map;

import org.springframework.cglib.beans.BeanCopier;

/**
 * @Author: gs
 * @Date: 2023/12/24 11:24
 * @Version: v1.0.0
 * @Description: TODO BeanCopier工具类
 **/
public class BeanCopierUtils {

    /**
     * BeanCopier缓存
     */
    public static Map<String, BeanCopier> beanCopierCacheMap = new HashMap<String, BeanCopier>();

    /**
     * 将source对象的属性拷贝到target对象中去
     * @param source source对象
     * @param target target对象
     */


    public static void copyProperties(Object source,Object target){
        String cacheKey = source.getClass().toString()+
                target.getClass().toString();

        BeanCopier beanCopier = null;

        if (!beanCopierCacheMap.containsKey(cacheKey)) {
            synchronized(BeanCopierUtils.class) {
                /*这是再次检查cacheKey是否存在于缓存中。
                这一步是必要的，因为在当前线程获取锁和执行这个检查之间，可能有其他线程已经插入了这个键。
                这是一种典型的“双重检查锁定”模式，用于提高性能和避免不必要的同步。
                */
                if (!beanCopierCacheMap.containsKey(cacheKey)) {
                    beanCopier = BeanCopier.create(source.getClass(), target.getClass(), false);
                    //false参数可能表示不使用转换器，这意味着直接复制属性而不进行任何类型转换
                    beanCopierCacheMap.put(cacheKey, beanCopier);
                }
            }
        } else {
            beanCopier = beanCopierCacheMap.get(cacheKey);
        }

        beanCopier.copy(source, target, null);
        //null参数表示不使用自定义转换器。
    }
}

/**
 * getClass():
 * 获取运行时类信息：getClass() 返回一个 Class 类型的实例，代表了调用这个方法的对象的确切运行时类。
 * 这个 Class 对象是在加载类时由 Java 虚拟机（JVM）创建的，包含了关于类的元数据，如类的名字、方法信息、字段信息等。
 *
 * --------
 * HashMap containsKey() 方法
 * containsKey() 方法检查 hashMap 中是否存在指定的 key 对应的映射关系。
 * containsKey() 方法的语法为： hashmap.containsKey(Object key)
 * 如果 hashMap 中存在指定的 key 对应的映射关系返回 true，否则返回 false
 * **/

/**
 * synchronized(BeanCopierUtils.class) { ... }:
 这是一个同步块，确保在任何时候只有一个线程可以执行这个代码块内的代码。
 这是为了防止多线程环境中的数据竞争和条件竞争。
 BeanCopierUtils.class是用于锁定的对象。在这种情况下，它锁定了整个BeanCopierUtils类，
 这意味着任何其他尝试进入任何同步在BeanCopierUtils.class上的代码块的线程都将被阻塞，
 直到当前线程离开这个同步块。

 **/
